# 能不能使用类装饰器去装饰函数呢？
# 如何使用该 Counter 去装饰指定的函数呢？作用是统计函数被调用的次数

class Counter:

    def __init__(self, func):
        self.count = 0
        self.func = func

    def __call__(self, *args, **kwargs):
        self.count += 1
        print(F"已经被调用了{self.count}次～")
        # 在这里真正的去调用函数，函数名字()即可调用
        return self.func(*args, **kwargs)


# 定义一个函数

# 装饰器去修饰一个函数
# 相当于 say_hi = Counter(say_hi)
@Counter
def say_hi():
    print("嗨~")


# 我们在调用 say_hi() 的时候相当于 调用了 Counter 对象的 counter() 自然就去执行了他的 __call__ 魔法方法
say_hi()
# 已经被调用了1次～
# 嗨~
say_hi()
# 已经被调用了2次～
# 嗨~
say_hi()
# 已经被调用了3次～
# 嗨~


# 剖析下上面的代码
# @Counter 装饰器就相当于
# say_hi = Counter(say_hi)
# 上面的say_hi = Counter(say_hi)就相当于实例化了一个Counter对象，将函数say_hi传递给了Counter的构造函数
# 并且赋值给 say_hi

print("====" * 50)

print(say_hi)
# <__main__.Counter object at 0x101194fd0>
# 我们发现 say_hi 已经不是函数 say_hi 了，而是 <__main__.Counter object at 0x101194fd0>,是一个 Counter 实例
# 因为 say_hi 就是 Counter的对象，在 say_hi() 就是相当于调用 Counter 的方法 __call__


# 我们在调用 say_hi() 的时候相当于 调用了 Counter 对象的 counter() 自然就去执行了他的 __call__ 魔法方法
# 我们在调用 say_hi() 的时候相当于 调用了 Counter 对象的 counter() 自然就去执行了他的 __call__ 魔法方法
# 我们在调用 say_hi() 的时候相当于 调用了 Counter 对象的 counter() 自然就去执行了他的 __call__ 魔法方法
# 我们在调用 say_hi() 的时候相当于 调用了 Counter 对象的 counter() 自然就去执行了他的 __call__ 魔法方法
